package com.adopapa.nezhacloud.authc.service;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import com.adopapa.nezhacloud.authc.domain.DepartmentInfo;
import com.adopapa.nezhacloud.authc.domain.UserInfo;
import com.adopapa.nezhacloud.authc.domain.UserInfoRepository;
import com.adopapa.nezhacloud.common.Tools;
import com.adopapa.nezhacloud.ddd.service.BaseDomainService;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;

@Service
public class UserInfoService extends BaseDomainService<UserInfo> {

	@Autowired
	private UserInfoRepository userInfoRepository;

	public UserInfo getUserInfoById(String id) {
		Optional<UserInfo> optional = userInfoRepository.findById(id);
		return optional.isPresent() ? optional.get() : null;
	}

	public UserInfo getUserInfoByLoginName(String loginName) {
		List<UserInfo> results = userInfoRepository.findByLoginName(loginName);
		return Tools.empty(results) ? null : results.get(0);
	}
	
	public List<UserInfo> getUserInfosByDepartment(DepartmentInfo departmentInfo) {
		return userInfoRepository.findByDepartmentInfo(departmentInfo);
	}

	public Page<UserInfo> getUserInfoPage(int pageNo, int pageSize, UserInfo userInfo) {
		PageRequest pageRequest = buildPageRequest(pageNo, pageSize, Order.desc("createTime"));
		Specification<UserInfo> specification = buildSpecification(userInfo);
		Page<UserInfo> page = userInfoRepository.findAll(specification, pageRequest);
		return page;
	}

	public UserInfo saveUserInfo(UserInfo userInfo) {
		return userInfoRepository.saveAndFlush(userInfo);
	}

	public List<UserInfo> saveUserInfos(List<UserInfo> userInfos) {
		return userInfoRepository.saveAllAndFlush(userInfos);
	}

	public void deleteUserInfo(String id) {
		userInfoRepository.deleteById(id);
	}

	public void deleteUserInfo(UserInfo userInfo) {
		userInfoRepository.delete(userInfo);
	}

	public void deleteUserInfos(String... ids) {
		userInfoRepository.deleteAllByIdInBatch(Arrays.asList(ids));
	}

	public void deleteUserInfos(List<UserInfo> userInfos) {
		userInfoRepository.deleteAllInBatch(userInfos);
	}

	@SuppressWarnings("serial")
	@Override
	public Specification<UserInfo> buildSpecification(UserInfo userInfo) {
		return new Specification<UserInfo>() {
			@Override
			public Predicate toPredicate(Root<UserInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new LinkedList<>();
				if (!Tools.empty(userInfo.getUserName())) {
					predicates.add(cb.like(root.get("userName"), //
							"%".concat(userInfo.getUserName()).concat("%")));
				}
				if (!Tools.empty(userInfo.getLoginName())) {
					predicates.add(cb.equal(root.get("loginName"), //
							userInfo.getLoginName()));
				}
				if (!Tools.empty(userInfo.getDepartmentInfo()) //
						&& !Tools.empty(userInfo.getDepartmentInfo().getId())) {
					predicates.add(cb.equal(root.join("departmentInfo").get("id"), //
							userInfo.getDepartmentInfo().getId()));
				}
				if (!Tools.empty(userInfo.getDepartmentInfo()) //
						&& !Tools.empty(userInfo.getDepartmentInfo().getDeptName())) {
					predicates.add(cb.equal(root.join("departmentInfo").get("deptName"), //
							"%".concat(userInfo.getDepartmentInfo().getDeptName()).concat("%")));
				}
				if (!Tools.empty(userInfo.getCreateTime())) {
					predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), //
							userInfo.getCreateTime()));
				}
				if (!Tools.empty(userInfo.getCreateTime2())) {
					predicates.add(cb.lessThan(root.get("createTime2"), //
							userInfo.getCreateTime2()));
				}
				return cb.and(predicates.toArray(new Predicate[0]));
			}

		};
	}

	// predicates.add(cb.equal(cb.substring(root.get("datagram"), 1, 23),
	// dataPrefix));

}
